﻿using System;
using System.Configuration;
using System.Web.Mvc;
using System.Web.Routing;
using Wedn.Net.Route.Configuration;

namespace Wedn.Net.Route
{
    /// <summary>
    /// 路由配置文件集合拓展方法内
    /// </summary>
    public static class RouteCollectionExtensions
    {
        private static string _defaultPage;
        private static string _extendName;
        /// <summary>
        /// 取默认页
        /// </summary>
        /// <param name="routes"></param>
        /// <returns></returns>
        public static string GetDefaultPage(this RouteCollection routes)
        {
            return _defaultPage;
        }
        /// <summary>
        /// 取拓展名
        /// </summary>
        /// <param name="routes"></param>
        /// <returns></returns>
        public static string GetExtendName(this RouteCollection routes)
        {
            return _extendName;
        }
        /// <summary>
        /// 根据配置的Routing规则来加载Routing规则
        /// </summary>
        public static void RegisterRoutes(this RouteCollection routes, RouteConfigurationSection section)
        {
            if (!section.Short.Enable && !section.Map.Enable)
                throw new ConfigurationErrorsException("Short与Map必须至少有一个开启.");

            _extendName = section.Extend;
            if (_extendName == "{db_extension}" || string.IsNullOrEmpty(_extendName))
                _extendName = Common.Setting.RewriteExtension;

            if (section.Short != null && section.Short.Enable)
                _defaultPage = section.Short.Default.Replace("{ext}", _extendName);
            else
                _defaultPage = section.Map.Default.Replace("{ext}", _extendName);
            //清除默认
            //routes.Clear();
            // Manipulate the Ignore List
            foreach (IgnoreItem ignoreItem in section.Ignore)
            {
                var ignoreConstraints = new RouteValueDictionary();

                foreach (Constraint constraint in ignoreItem.Constraints)
                    ignoreConstraints.Add(constraint.Name, constraint.Value);

                routes.IgnoreRoute(ignoreItem.Url, ignoreConstraints);
            }
            // Maniplute the short Routing Table
            if (section.Short != null && section.Short.Enable)
            {
                foreach (RoutingItem item in section.Short)
                {
                    var defaults = new RouteValueDictionary();
                    var constraints = new RouteValueDictionary();

                    if (item.Controller != string.Empty)
                        defaults.Add("controller", item.Controller);

                    if (item.Action != string.Empty)
                        defaults.Add("action", item.Action);

                    foreach (Parameter param in item.Paramaters)
                    {
                        defaults.Add(param.Name, param.Value);
                        if (!string.IsNullOrEmpty(param.Constraint))
                        {
                            constraints.Add(param.Name, param.Constraint.Replace("{ext}", _extendName));
                        }
                    }
                    routes.MapRoute(item.Name, item.Domain, item.Url.Replace("{ext}", _extendName), defaults, constraints);
                }
            }

            // Manipluate the Routing Table
            if (section.Map != null && section.Map.Enable)
            {
                foreach (RoutingItem item in section.Map)
                {
                    var defaults = new RouteValueDictionary();
                    var constraints = new RouteValueDictionary();

                    if (item.Controller != string.Empty)
                        defaults.Add("controller", item.Controller);

                    if (item.Action != string.Empty)
                        defaults.Add("action", item.Action);

                    foreach (Parameter param in item.Paramaters)
                    {
                        defaults.Add(param.Name, param.Value);
                        if (!string.IsNullOrEmpty(param.Constraint))
                        {
                            constraints.Add(param.Name, param.Constraint.Replace("{ext}", _extendName));
                        }
                    }

                    routes.MapRoute(item.Name, item.Domain, item.Url.Replace("{ext}", _extendName), defaults, constraints);
                }
            }
        }
        /// <summary>
        /// 忽略集合
        /// </summary>
        /// <param name="routes"></param>
        /// <param name="url"></param>
        /// <param name="constraints"></param>
        public static void IgnoreRoute(this RouteCollection routes, string url, RouteValueDictionary constraints)
        {
            if (routes == null) throw new ArgumentNullException("routes");
            if (url == null) throw new ArgumentNullException("url");
            var ignore = new IgnoreRoute(url) { Constraints = constraints };
            routes.Add(ignore);
        }

        /// <summary>
        /// 框架的这个方法的defaults、constraints参数都是Object类型的，只好重写
        /// </summary>
        /// <param name="routes">路由实体集合</param>
        /// <param name="name">路由名称</param>
        /// <param name="domain">域名</param>
        /// <param name="url">URL路径</param>
        /// <param name="defaults"></param>
        /// <param name="constraints"></param>
        public static void MapRoute(this RouteCollection routes, string name, string domain, string url, RouteValueDictionary defaults, RouteValueDictionary constraints)
        {
            if (routes == null) throw new ArgumentNullException("routes");
            if (url == null) throw new ArgumentNullException("url");
            //var route = new System.Web.Routing.Route(url, new MvcRouteHandler())
            //{
            //    Defaults = defaults,
            //    Constraints = constraints
            //};
            //var route = new WednRoute(url, new MvcRouteHandler())
            //{
            //    Defaults = defaults,
            //    Constraints = constraints
            //};
            var route = new WednRoute(domain, url, defaults, constraints, new MvcRouteHandler());
            routes.Add(name, route);
        }
        /// <summary>
        /// 取结点
        /// </summary>
        /// <returns></returns>
        public static RouteConfigurationSection GetSection()
        {
            var section = ConfigurationManager.GetSection("route") as RouteConfigurationSection;
            return section;
        }
    }


    sealed class IgnoreRoute : System.Web.Routing.Route
    {
        public IgnoreRoute(string url) : base(url, new StopRoutingHandler()) { }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { return null; }
    }
}
